#include <jni.h>
#include <stdlib.h>

#include "haptimap_types.h"
#include "haptimap_android_jni.h"
#include "common.h"

jint Java_org_haptimap_HaptiMap_GeoPluginInquire(JNIEnv *env, jobject wrapper, jobject cap, jintArray ptr_count)
{
    hm_t *hm = GET_HM(wrapper);
    int count;

    if(hm_geo_plugin_inquire(hm, GET_ORDINAL(cap), &count) != HM_SUCCESS)
        return HM_FAILURE;

    STORE_INT(ptr_count, count);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoPluginGetId(JNIEnv *env, jobject wrapper, jobject cap, jint n, jintArray ptr_id)
{
    hm_t *hm = GET_HM(wrapper);
    int id;

    if(hm_geo_plugin_get_id(hm, GET_ORDINAL(cap), n, &id) != HM_SUCCESS)
        return HM_FAILURE;

    STORE_INT(ptr_id, id);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoPluginGetName(JNIEnv *env, jobject wrapper, jint id, jobject str_name)
{
    hm_t *hm = GET_HM(wrapper);
    const char *name;
    jstring str;

    if(hm_geo_plugin_get_name(hm, id, &name) != HM_SUCCESS)
        return HM_FAILURE;

    /* First convert C string to Java string */
    str = (*env)->NewStringUTF(env, name);
    /* Then append this Java string to the StringBuilder object */
    (*env)->CallObjectMethod(env, str_name, (*env)->GetMethodID(env, (*env)->GetObjectClass(env, str_name), 
                                                                "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;"),
                             str);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoGetLeadPlugin(JNIEnv *env, jobject wrapper, jintArray ptr_id)
{
    hm_t *hm = GET_HM(wrapper);
    int id;

    if(hm_geo_plugin_lead_get(hm, &id) != HM_SUCCESS)
        return HM_FAILURE;

    STORE_INT(ptr_id, id);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoSetLeadPlugin(JNIEnv *env, jobject wrapper, jint id)
{
    hm_t *hm = GET_HM(wrapper);

    return hm_geo_plugin_lead_set(hm, id);
}

jint Java_org_haptimap_HaptiMap_GeoPluginCoversPoint(JNIEnv *env, jobject wrapper, jint id, jintArray point_arr, jintArray ptr_covered)
{
    hm_t *hm = GET_HM(wrapper);
    int point[2];
    int covered;

    (*env)->GetIntArrayRegion(env, point_arr, 0, 2, point);
    if(hm_geo_plugin_point_covered(hm, id, point, &covered) != HM_SUCCESS)
        return HM_FAILURE;

    STORE_INT(ptr_covered, covered);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoPluginCoversArea(JNIEnv *env, jobject wrapper, jint id, jintArray bbox_arr, jintArray ptr_covered)
{
    hm_t *hm = GET_HM(wrapper);
    int bbox[4];
    int covered;

    (*env)->GetIntArrayRegion(env, bbox_arr, 0, 4, bbox);
    if(hm_geo_plugin_area_covered(hm, id, bbox, &covered) != HM_SUCCESS)
        return HM_FAILURE;

    STORE_INT(ptr_covered, covered);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoPluginFeatureTypes(JNIEnv *env, jobject wrapper, jint id, jintArray feature_list_arr, jintArray num_features_arr)
{
    hm_t *hm = GET_HM(wrapper);
    int *feature_list, num_features, capacity;

    (*env)->GetIntArrayRegion(env, num_features_arr, 0, 1, &capacity);
    feature_list = malloc(capacity * sizeof(int));
    num_features = capacity;
    if(hm_geo_plugin_feature_types(hm, id, feature_list, &num_features) != HM_SUCCESS)
    {
        free(feature_list);
        return HM_FAILURE;
    }
    (*env)->SetIntArrayRegion(env, num_features_arr, 0, 1, &num_features);
    if(num_features > capacity)
        num_features = capacity;
    if(num_features > 0)
        (*env)->SetIntArrayRegion(env, feature_list_arr, 0, num_features, feature_list);
    free(feature_list);

    return HM_SUCCESS;
}

jint Java_org_haptimap_HaptiMap_GeoPluginEnableFeature(JNIEnv *env, jobject wrapper, jint id, jint feature_id)
{
    hm_t *hm = GET_HM(wrapper);

    return hm_geo_plugin_feature_enable(hm, id, feature_id);
}

jint Java_org_haptimap_HaptiMap_GeoPluginDisableFeature(JNIEnv *env, jobject wrapper, jint id, jint feature_id)
{
    hm_t *hm = GET_HM(wrapper);

    return hm_geo_plugin_feature_disable(hm, id, feature_id);
}

jint Java_org_haptimap_HaptiMap_GeoPluginLoadBBox(JNIEnv *env, jobject wrapper, jint id, jintArray bbox_arr)
{
    hm_t *hm = GET_HM(wrapper);
    int bbox[4];

    (*env)->GetIntArrayRegion(env, bbox_arr, 0, 4, bbox);

    return hm_geo_plugin_load_bbox(hm, id, bbox);
}

jint Java_org_haptimap_HaptiMap_GeoFlushStorage(JNIEnv *env, jobject wrapper)
{
    hm_t *hm = GET_HM(wrapper);

    return hm_geo_storage_flush(hm);
}

jint Java_org_haptimap_HaptiMap_GeoEraseStorage(JNIEnv *env, jobject wrapper)
{
    hm_t *hm = GET_HM(wrapper);

    return hm_geo_storage_erase(hm);
}
